package com.game.optimize.enums;

import com.dashanchessgame.tools.WinUtils;

import javax.swing.*;

/**
 * 棋子行动能力枚举
 *
 * @author Nessis
 * @since 2023-02-28 17:10
 */
public enum ChessMoveRuleEnum {
    /**
     * 卒走直
     */
    ARM("B", (map, nowLineNumber, nowColumnNumber, toLineNumber, toColumnNumber, isChessColor) -> {

        //得到他们之间相差的行数和列数后用来进行判断是否可以去
        //相差的列号
        int istoColumnNumber = toColumnNumber - nowColumnNumber;
        //相差的行号
        int istoLineNumber = toLineNumber - nowLineNumber;
        //判断是否可以前进以及进入对方阵营的走法
        int adsIstoColumnNumber = Math.abs(istoColumnNumber);
        // 判断哪方走
        if (isChessColor) {
            //如果行号<= 4表示黑卒未过河行动受限制只能向前进一格
            //黑卒没有过河
            if (nowLineNumber <= 4) {
                //未过河相差的行数不等于0，并且相差的列数等于1 表示可以可以前进一步
                //如果不是直接false不能移动
                return istoColumnNumber == 0 && istoLineNumber == 1;
            } else {
                //判断黑卒过河，向下前进一格
                if (!((adsIstoColumnNumber == 1 && istoLineNumber == 0) || (adsIstoColumnNumber == 0 && istoLineNumber == 1))) {
                    return false;
                } else {
                    //判断如果此时的位置是对方将军所在的位置确认游戏结束黑方胜利，跳出胜利
                    if (map[toLineNumber][toColumnNumber] == 'J') {
                        JOptionPane.showMessageDialog(null, "黑方胜利！");
                    }
                    //如果不是返回true
                    return true;
                }
            }
        } else {
            if (nowLineNumber >= 5) {
                //判断红卒未过河
                //红卒未过河，向上前进一格
                return istoColumnNumber == 0 && istoLineNumber == -1;
            } else {
                //红卒过河进行判断位置过河坐标
                if (!((adsIstoColumnNumber == 1 && istoLineNumber == 0) || (adsIstoColumnNumber == 0 && istoLineNumber == -1))) {
                    return false;
                } else {
                    if (map[toLineNumber][toColumnNumber] == 1000 + 'J') {
                        JOptionPane.showMessageDialog(null, "红方胜利！");
                    }
                    return true;
                }
            }
        }
    }),
    /**
     * 炮
     */
    CANNON("P", (map, nowLineNumber, nowColumnNumber, toLineNumber, toColumnNumber, isChessColor) -> {
        int istoLineNumber = Math.abs(toLineNumber - nowLineNumber);   //计算出相差的行号值
        int istoColumnNumber = Math.abs(toColumnNumber - nowColumnNumber); //计算出相差的列号值
//        判断是不是走直线
        if (!((istoLineNumber != 0 && istoColumnNumber == 0) || (istoLineNumber == 0 && istoColumnNumber != 0))) {
            return false;//如果不是返回false
        }
        //判断棋子行走路径上有没有棋子
        int count = 0;
        int from, to;
        //目标点没有棋子且目标点和起始点之间没有棋子，则成功移动
        //目标点有棋子，且为敌方棋子，且目标点和初始点之间有一个棋子，成功。
        if (istoLineNumber == 0) {  //横着像右
            if (nowColumnNumber < toColumnNumber) { //向左走
                //
                from = nowColumnNumber + 1;
                to = toColumnNumber;
            } else {//横着走向右
                from = toColumnNumber + 1;
                to = nowColumnNumber;
            }
            //循环遍历数组查询路径上是否由其子一直到，有的话count++
            for (int i = from; i < to; i++) {
                if (map[nowLineNumber][i] != 0) {
                    count++;
                }
            }
            //判断count如果是0则线路上没有棋子，如果是
            if (map[toLineNumber][toColumnNumber] == 0 && count == 0) {
                System.out.println("行走路径上没有棋子");
                return true;
            }
            if (map[toLineNumber][toColumnNumber] == 0 && count == 1) {
                System.out.println("要去的坐标为上没有棋子不能跳过去");
                return false;
            }
            //黑方，对面为红方;  红方，对面为黑方。 1000作为判断红黑双方的凭着具体详细见 CanvasChess中的map数据
            if ((map[toLineNumber][toColumnNumber] != 0 && ((isChessColor && map[toLineNumber][toColumnNumber] < 1000)) || ((!isChessColor && map[toLineNumber][toColumnNumber] > 1000)) && count == 1)) {
                //将军
                return WinUtils.win(map,toLineNumber,toColumnNumber,isChessColor);
                //否则返回true
            } else {
                return false;
            }
        } else { //竖着走
            //判断走向如果现在行数小于要去的行数就是向下走，反之向上
            if (nowLineNumber < toLineNumber) {
                from = nowLineNumber + 1;
                to = toLineNumber;
            } else {
                from = toLineNumber + 1;
                to = nowLineNumber;
            }
            for (int i = from; i < to; i++) {
                if (map[i][nowColumnNumber] != 0) {
                    System.out.println(map[i][nowColumnNumber]);
                    count++;
                }
            }
            //如果map[toLineNumber][toLineNumber]==0 count为0表示中间路径上面没有一个棋子该位置上没有一个棋子
            if (map[toLineNumber][toColumnNumber] == 0 && count == 0) {
                return true;
            }
            //如果map[toLineNumber][toLineNumber]==0 count为1表示中间路径上面有一个棋子可以作为跳板进行打击map[toLineNumber][toLineNumber]
            if (map[toLineNumber][toColumnNumber] != 0 && count == 1 ) {
                return WinUtils.win(map,toLineNumber,toColumnNumber,isChessColor);
            }
            return false;
        }
    }),
    /**
     * 车
     */
    CAR("C", (map, nowLineNumber, nowColumnNumber, toLineNumber, toColumnNumber, isChessColor) -> {

        int istoLineNumber = Math.abs(toLineNumber - nowLineNumber);   //计算出相差的行号值
        int istoColumnNumber = Math.abs(toColumnNumber - nowColumnNumber); //计算出相差的列号值
        //判断是不是直线,不是直线直接返回false
        if ((nowLineNumber != toLineNumber  && istoColumnNumber !=0) || (nowColumnNumber!=toColumnNumber && istoLineNumber!=0)) {
            return false;
        }

        //判断棋子行走路径上有没有棋子
        int from, to;
        //横着走
        if (istoLineNumber == 0 ) {
            //判断向左
            if (nowColumnNumber < toColumnNumber) {
                //
                from = nowColumnNumber + 1;
                to = toColumnNumber;
            } else {//横着走向右
                from = toColumnNumber + 1;
                to = nowColumnNumber;
            }
            //循环遍历数组查询路径上是否由其子一直到，有的话count++
            for (int i = from; i < to; i++) {
                if (map[nowLineNumber][i] != 0) {
                    return false;  //中间有棋子，失败！！
                }
            }
        } else {
            //竖着走向上向下
            if (nowLineNumber < toLineNumber) {
                //
                from = nowLineNumber + 1;
                to = toLineNumber;
            } else {
                from = toLineNumber + 1;
                to = nowLineNumber;
            }
            //循环遍历数组查询路径上是否由其子一直到，有的话count++
            for (int i = from; i < to; i++) {
                if (map[i][nowColumnNumber] != 0) {
                    return false;  //中间有棋子，失败！！
                }
            }
        }
        //调用了判断哪方获胜的方法
        return WinUtils.win(map, toLineNumber, toColumnNumber, isChessColor);

    }),
    /**
     * 将
     */
    MATE("J", (map, nowLineNumber, nowColumnNumber, toLineNumber, toColumnNumber, isChessColor) -> {
        int count = 0;//用来统计棋子的行径路上有没有棋子有的话count就加1
        int istoLineNumber = Math.abs(nowLineNumber - toLineNumber);  // 获取相差的行数
        int istoColumnNumber = Math.abs(nowColumnNumber - toColumnNumber);// 获取相差的列数
        int minR = nowLineNumber < toLineNumber ? nowLineNumber : toLineNumber;
        int maxR = nowLineNumber > toLineNumber ? nowLineNumber : toLineNumber;
        for (int i = minR + 1; i < maxR; i++) {//如果双方 将军之间有棋子的话，不可走棋
            if (istoColumnNumber == 0 && map[i][nowColumnNumber] != 0) {
                count = 1;
                return false;
            }
        }
        //判断将的位置是不是在范围移动范围里面
        if ((((istoColumnNumber == 1 && istoLineNumber == 0) || (istoColumnNumber == 0 && istoLineNumber == 1)
                && (toLineNumber <= 2 && toColumnNumber <= 5)) || (toLineNumber >= 7 && toLineNumber <= 9)) || count == 0) {

            return WinUtils.win(map, toLineNumber, toColumnNumber, isChessColor);

        } else {
            return false;
        }
    }),
    /**
     * 象
     */
    ELEPHANT("X", (map, nowLineNumber, nowColumnNumber, toLineNumber, toColumnNumber, isChessColor) -> {
        //获取相差的行数和列数
        int istoLineNumber = Math.abs(nowLineNumber - toLineNumber);
        int istoColumnNumber = Math.abs(nowColumnNumber - toColumnNumber);

        //判断是否满足象的不行规则如果去的位置相差行数不是2相差的列数不是2 返回false 不符合规则
        if (!(istoLineNumber == 2 && istoColumnNumber == 2) ) {
            return false;
        }else {
            int lineNumber = (nowLineNumber+toLineNumber)/2;
            int columnNumber = (nowColumnNumber+toColumnNumber)/2;
            if (isChessColor){
                //黑象 判断相差的行数上有没有棋子并且 没有过河
                return map[lineNumber][columnNumber] ==0 && toLineNumber<=4 ;
            }else {
                //红象 判断相差的行数上有没有棋子并且 没有过河
                return map[lineNumber][columnNumber] ==0 && toLineNumber>4;
            }
        }
    }),
    /**
     * 马
     */
    HORSE("M", (map, nowLineNumber, nowColumnNumber, toLineNumber, toColumnNumber, isChessColor) -> {
        //获取相差的行数和列数
        int istoLineNumber = Math.abs(nowLineNumber - toLineNumber);
        int istoColumnNumber = Math.abs(nowColumnNumber - toColumnNumber);
        int listLineNumber = 0;
        int columnNumber = 0;
        //判断马是不是走的日
        if ((istoLineNumber == 2 && istoColumnNumber == 1) || (istoLineNumber == 1 && istoColumnNumber == 2)) {
            //判断横着走正上方的的棋子
            if (istoColumnNumber == 1) {
                listLineNumber = (nowLineNumber + toLineNumber) / 2;
                columnNumber = nowColumnNumber;
            } else {
//              判断竖着走正上方的棋子
                listLineNumber = nowLineNumber;
                columnNumber = (nowColumnNumber + toColumnNumber) / 2;
            }
//             判断行进方向正上方有没有棋子
            if (map[listLineNumber][columnNumber] == 0) {
//                判断对方是不是将
                return WinUtils.win(map, toLineNumber, toColumnNumber, isChessColor);
            }
        }
        return false;
    }),
    /**
     * 士
     */
    SHI("S", (map, nowLineNumber, nowColumnNumber, toLineNumber, toColumnNumber, isChessColor) -> {
        //获取相差的行数和列数
        int istoLineNumber = Math.abs(nowLineNumber - toLineNumber);
        int istoColumnNumber = Math.abs(nowColumnNumber - toColumnNumber);

        //判断方向是不是斜着走的，相差的行和列都必须是1才可以,不能超出士的行进范围田字格
        if (istoLineNumber == 1 && istoColumnNumber == 1 && ((toLineNumber <= 10 && toLineNumber >= 8) || (toColumnNumber <= 5 && toColumnNumber >= 3))) {
            return true;
        } else {
            return false;
        }

    }),
    ;
    final String type;

    final MoveAbility moveAbility;

    ChessMoveRuleEnum(String type, MoveAbility moveAbility) {
        this.type = type;
        this.moveAbility = moveAbility;
    }

    interface MoveAbility {
        /**
         * chessCheck  检查落子是否合法
         *
         * @param map             地图
         * @param nowLineNumber   当前棋子的行号
         * @param nowColumnNumber 当前棋子的列号
         * @param toLineNumber    棋子要去的行号
         * @param toColumnNumber  棋子要去的列号
         * @param isChessColor    判断棋子的攻守方  黑的返回true 红的返回false
         * @return 如果可以去，返回true, 否则返回false
         */
        boolean chessCheck(int[][] map, int nowLineNumber, int nowColumnNumber, int toLineNumber, int toColumnNumber, boolean isChessColor);
    }

    public String getType() {
        return type;
    }

    public MoveAbility getMoveAbility() {
        return moveAbility;
    }
}
